﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MySql.Data.MySqlClient;
using System.Data;

namespace CamadaDeDados
{
    public enum ComandosBanco
    {
        Insere,
        Altera,
        Deleta,
        BuscaPorID,
        Lista
    }

    public class Conexao                      
    {
        private const string StringConexao = "server=localhost;User Id=root;password=ale1992;database=finanflex";

        private MySqlConnection _conexao;
        private static MySqlTransaction _transacao;
        private static DataSet _ds = new DataSet();
        private MySqlCommand _comando;
        private string _nomeTabela;

        #region Construtores

        public Conexao(string pNomeTabela)
        {
            if (_conexao == null)
            {
                _conexao = new MySqlConnection(StringConexao);
                _conexao.Open();
            }
            _nomeTabela = pNomeTabela;
            _comando = _conexao.CreateCommand();
            _comando.CommandType = CommandType.StoredProcedure;
        }

        public Conexao(MySqlConnection pConexao, string pNomeTabela)
        {
            _conexao = pConexao;
            _nomeTabela = pNomeTabela;
            _comando = _conexao.CreateCommand();
            _comando.CommandType = CommandType.StoredProcedure;
            
        }

        #endregion

        public static MySqlConnection Conectar()
        {
            MySqlConnection _objConexao = new MySqlConnection(StringConexao);

            _objConexao.Open();

            return _objConexao;
        }
        /// <summary>
        /// Método para adicionar um novo parametro ao comando
        /// </summary>
        /// <param name="pParametro"></param>
        /// <param name="pValor"></param>
        public void AdicionarParametro(string pParametro, object pValor)
        {
            _comando.Parameters.AddWithValue("p_" + pParametro, pValor);
        }

        /// <summary>
        /// Executa o comando sql (Insert, Update, Delete) no banco
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        public void ExecutarComando(string pComando)
        {
            try
            {
                _comando.CommandText = "sp_" + _nomeTabela + "_" + pComando;
                _comando.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Executa o comando sql(Insert, Update, Delete) no banco
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        /// <returns></returns>
        public void ExecutarComando(ComandosBanco pComando)
        {
            this.ExecutarComando(pComando.ToString());
        }

        /// <summary>
        /// Executa o comando e retorna um data table
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        /// <returns>Data table Carregado</returns>
        public DataTable RetornarDataTable(string pComando)
        {
            try
            {
                // define o nome do comando a ser executado
                _comando.CommandText = "sp_" + _nomeTabela + "_" + pComando;
                // cria uma nova instância do objeto DataAdapter
                MySqlDataAdapter _da = new MySqlDataAdapter(_comando);

                // verifica se a tabela existe no dataset para apaga-lá
                if (_ds.Tables.Contains(_nomeTabela)) _ds.Tables.Remove(_nomeTabela);

                // cria a tabela no dataset
                _ds.Tables.Add(_nomeTabela);

                // desativa a verificação de restrições enquanto a tabela é carregada
                _ds.EnforceConstraints = false;

                // desativa a indexação e a notificação
                _ds.Tables[_nomeTabela].BeginLoadData();

                // carrega os dados
                _da.Fill(_ds,_nomeTabela);

                // ativa a indexação e a notificação
                _ds.Tables[_nomeTabela].EndLoadData();

                // retorna a tabela
                return _ds.Tables[_nomeTabela];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Executa o comando e retorna um data table
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        /// <returns>Data table Carregado</returns>
        public DataTable RetornarDataTable(ComandosBanco pComando)
        {
            return RetornarDataTable(pComando.ToString());
        }

        /// <summary>              
        /// Método para retornar um DataReader
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        /// <returns>DataReader carregado</returns>
        public MySqlDataReader RetornarDataReader(string pComando)
        {                                     
            try
            {
                _comando.CommandText = "sp_" + _nomeTabela + "_" + pComando;
                return _comando.ExecuteReader();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Método para retornar um DataReader
        /// </summary>
        /// <param name="pComando">Comando a ser executado</param>
        /// <returns>DataReader carregado</returns>
        public MySqlDataReader RetornarDataReader(ComandosBanco pComando)
        {
            return RetornarDataReader(pComando.ToString());
        }

        /// <summary>
        /// Método para iniciar a transação de dados com o banco
        /// </summary>
        public void IniciarTransacao()
        {
            if (_transacao == null)
                _transacao = _conexao.BeginTransaction();

            _comando.Transaction = _transacao;
        }

        /// <summary>
        /// Método para cancelar as alterações realizadas no banco
        /// </summary>
        public void RollBack()
        {
            if (_comando.Transaction != null)
            {
                _transacao.Rollback();
                _comando.Transaction = null;
                _transacao = null;
            }
        }

        /// <summary>
        /// Método para salvar as alterações realizadas no banco
        /// </summary>
        public void Commit()
        {
            if (_comando.Transaction != null)
            {
                _transacao.Commit();
                _transacao = null;
                _comando.Transaction = null;
            }
        }
    }
}
